/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frreport_convert.c                                 */
/*  NOTE      = 上报数据转换                                       */
/*  DATE      = 2014/11/26 guojq                                   */
/*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "frcomm.h"
#include "frmem.h"
#include "frlist.h"
#include "frlog.h"

#include "conntrack.h"
#include "module.h"
#include "frreport_comm.h"

#define FRREPORT_HEADER_SIZE        104
#define FRREPORT_STAT_PORT_SIZE     48
#define FRREPORT_STAT_CONN_SIZE     48
#define FRREPORT_L7DATA_SIZE        32
#define FRREPORT_STAT_L4_TCP_SIZE   64

/*******************************************************************************
*  FUNC     :  转换数据包头
*  ARGS     :
*           :  i_flag_request   (FR_YES:request; FR_NO:response)
*           :  p_st_hdr         (Frreport_header*)
*           :  p_output         (数据出力空间)
*           :  ui_out_size      (数据出力空间大小 >= 92)
*           :  p_ui_used        (实际使用的空间大小)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frreport_conver_header(Frreport_type em_type, Frreport_type_l7data em_type_l7data, Frreport_header *p_st_hdr
                                     , char *p_output, unsigned int ui_out_size)
{
    char *p_pos;
    unsigned int ui_len = 0;

    if(p_st_hdr == NULL || p_output == NULL || ui_out_size < FRREPORT_HEADER_SIZE)
        return FR_FAIL;

    p_pos = p_output;

    memcpy(p_pos+ui_len, APM_REPORT_MAGIC_NUMBER, strlen(APM_REPORT_MAGIC_NUMBER));
    ui_len += strlen(APM_REPORT_MAGIC_NUMBER);

    memcpy(p_pos+ui_len, p_st_hdr->arr_version, sizeof(p_st_hdr->arr_version));
    ui_len += sizeof(p_st_hdr->arr_version);

    *(long *)(p_pos+ui_len) = frhton64(p_st_hdr->ul_body_len);
    ui_len += sizeof(long);

    memcpy(p_pos+ui_len, p_st_hdr->arr_msg_id, 36);
    ui_len += 36;

    memcpy(p_pos+ui_len, p_st_hdr->arr_agent_from, 36);
    ui_len += 36;

    *(p_pos+ui_len) = p_st_hdr->c_flag_zip;
    ui_len += sizeof(char);

    *(long *)(p_pos+ui_len) = frhton64(p_st_hdr->st_event_timestamp.tv_sec*1000+(long)(p_st_hdr->st_event_timestamp.tv_usec/1000) );
    ui_len += sizeof(long);

    switch(em_type)
    {
        case FRREPORT_TYPE_STAT_PORT:
            memcpy(p_pos+ui_len, "PORT", 4);
            break;
        case FRREPORT_TYPE_STAT_CONN:
            memcpy(p_pos+ui_len, "STAT", 4);
            break;
        case FRREPORT_TYPE_L7DATA:
            if(em_type_l7data == FRREPORT_TYPE_L7DATA_REQ)
                memcpy(p_pos+ui_len, "REQ ", 4);
            else if(em_type_l7data == FRREPORT_TYPE_L7DATA_RESP)
                memcpy(p_pos+ui_len, "RESP", 4);
            else if(em_type_l7data == FRREPORT_TYPE_L7DATA_PUB)
                memcpy(p_pos+ui_len, "PUB ", 4);
            else if(em_type_l7data == FRREPORT_TYPE_L7DATA_SUB)
                memcpy(p_pos+ui_len, "SUB ", 4);
            else if(em_type_l7data == FRREPORT_TYPE_L7DATA_NOTIFY)
                memcpy(p_pos+ui_len, "NIFY", 4);
            else if(em_type_l7data == FRREPORT_TYPE_L7DATA_UPDATE)
                memcpy(p_pos+ui_len, "UPDT", 4);
            break;
        case FRREPORT_TYPE_STAT_L4:
            memcpy(p_pos+ui_len, "L4IF", 4);
            break;
        default:
            memcpy(p_pos+ui_len, "ERR ", 4);
            break;
    }
    ui_len += 4;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  l4 tcp 数据
*  ARGS     :  p_st_stat_port   (Frreport_stat_port*)
*           :  p_st_str         (Frstr*)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frreport_conver_stat_l4_tcp(Frreport_stat_l4_tcp  *p_st_stat_l4_tcp, Frstr *p_st_str)
{
    char arr_buff[FRREPORT_STAT_L4_TCP_SIZE+1];
    char *p_pos;
    unsigned int ui_len = 0;

    if(p_st_stat_l4_tcp == NULL || p_st_str == NULL)
        return FR_FAIL;

    p_pos = arr_buff;
    *(int *)(p_pos+ui_len) = frhton32(p_st_stat_l4_tcp->ip_proto);
    ui_len += sizeof(int);

    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_l4_tcp->dst_ip);
    ui_len += sizeof(long);

    *(int *)(p_pos+ui_len) = frhton32(p_st_stat_l4_tcp->dst_port);
    ui_len += sizeof(int);

    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_l4_tcp->ul_tx_bytes);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_l4_tcp->ul_rx_bytes);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_l4_tcp->ul_conns);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_l4_tcp->ul_acks);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_l4_tcp->ul_resets);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_l4_tcp->ul_zero_win);
    ui_len += sizeof(long);
    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);

    return FR_SUCC;
}


/*******************************************************************************
*  FUNC     :  端口统计数据
*  ARGS     :  p_st_stat_port   (Frreport_stat_port*)
*           :  p_st_str         (Frstr*)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frreport_conver_stat_port(Frreport_stat_port  *p_st_stat_port, Frstr *p_st_str)
{
    char arr_buff[FRREPORT_STAT_PORT_SIZE+1];
    char *p_pos;
    unsigned int ui_len = 0;

    if(p_st_stat_port == NULL || p_st_str == NULL)
        return FR_FAIL;

    p_pos = arr_buff;
    *(int *)(p_pos+ui_len) = frhton32(p_st_stat_port->ip_proto);
    ui_len += sizeof(int);

    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_port->dst_ip);
    ui_len += sizeof(long);

    *(int *)(p_pos+ui_len) = frhton32(p_st_stat_port->dst_port);
    ui_len += sizeof(int);

    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_port->ul_tx_bytes);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_port->ul_rx_bytes);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_port->ul_tx_pkts);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_port->ul_rx_pkts);
    ui_len += sizeof(long);

    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  连接数统计数据
*  ARGS     :  p_st_stat_conn   (Frreport_stat_conn*)
*           :  p_st_str         (Frstr*)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frreport_conver_stat_conn(Frreport_stat_conn  *p_st_stat_conn, Frstr *p_st_str)
{
    char arr_buff[FRREPORT_STAT_CONN_SIZE+1];
    char *p_pos;
    unsigned int ui_len = 0;

    if(p_st_stat_conn == NULL || p_st_str == NULL)
        return FR_FAIL;

    p_pos = arr_buff;
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_conn->src_ip);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_conn->dst_ip);
    ui_len += sizeof(long);
    *(int *)(p_pos+ui_len) = frhton32(p_st_stat_conn->dst_port);
    ui_len += sizeof(int);
    *(int *)(p_pos+ui_len) = frhton32(p_st_stat_conn->ui_conns);
    ui_len += sizeof(int);
    *(int *)(p_pos+ui_len) = frhton32(p_st_stat_conn->ui_refused);
    ui_len += sizeof(int);
    *(int *)(p_pos+ui_len) = frhton32(p_st_stat_conn->ui_reset);
    ui_len += sizeof(int);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_conn->ul_tx_bytes);
    ui_len += sizeof(long);
    *(long *)(p_pos+ui_len) = frhton64(p_st_stat_conn->ul_rx_bytes);
    ui_len += sizeof(long);

    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  字符串数据格式组织
*  ARGS     :  p_st_str         (Frstr*)
*           :  p_data           (出力数据)
*           :  ui_data_len      (出力数据长度)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __frreport_conver_str(Frstr *p_st_str, const char *p_data, unsigned int ui_data_len)
{
    char arr_buff[10];
    char *p_pos;
    unsigned int ui_len = 0;

    if(p_st_str == NULL )
        return;

    if(p_data == NULL)
        ui_data_len = 0;

    p_pos = arr_buff;
    *(int *)(p_pos+ui_len) = frhton32(ui_data_len);
    ui_len += sizeof(int);
    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);

    if(ui_data_len > 0)
        frstr_append(p_st_str, p_data, ui_data_len);

    return;
}

/*******************************************************************************
*  FUNC     :  long数据格式组织
*  ARGS     :  p_st_str         (Frstr*)
*           :  ll_data           (出力数据)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __frreport_conver_llong(Frstr *p_st_str, long long ll_data)
{
    char arr_buff[20];
    char *p_pos;
    unsigned int ui_len = 0;

    if(p_st_str == NULL )
        return;

    p_pos = arr_buff;
    *(int *)(p_pos+ui_len) = frhton32(sizeof(long)); //不是sizeof(int)
    ui_len += sizeof(int);

    *(long long *)(p_pos+ui_len) = frhton64(ll_data);
    ui_len += sizeof(long long);
    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);

    return;
}

/*******************************************************************************
*  FUNC     :  long数据格式组织
*  ARGS     :  p_st_str         (Frstr*)
*           :  d_data           (出力数据)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __frreport_conver_double(Frstr *p_st_str, double d_data)
{
    char arr_buff[20];
    char *p_pos;
    unsigned int ui_len = 0;
    Frdata_bits st_data_bits;

    if(p_st_str == NULL )
        return;

    p_pos = arr_buff;
    *(int *)(p_pos+ui_len) = frhton32(sizeof(double)); //不是sizeof(int)
    ui_len += sizeof(int);

    st_data_bits.d_value = d_data;
    *(long *)(p_pos+ui_len) = frhton64(st_data_bits.l_value);
    ui_len += sizeof(long);
    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);

    return;
}

#ifdef FRFRAME_CONVER_DOUBLE_DATE
/*******************************************************************************
*  FUNC     :  double格式组织
*  ARGS     :  p_st_str         (Frstr*)
*           :  p_data           (出力数据)
*           :  ui_data_len      (出力数据长度)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __frreport_conver_double(Frstr *p_st_str, const char *p_data, unsigned int ui_data_len)
{
    char arr_buff[50];
    char *p_pos;
    double d_data = 0.0;
    unsigned int ui_len = 0;

    if(p_st_str == NULL )
        return;

    if(p_data == NULL)
        ui_data_len = 0;

    p_pos = arr_buff;
    *(int *)(p_pos+ui_len) = frhton32(sizeof(double));
    ui_len += sizeof(double);
    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);

    if(ui_data_len > 0)
    {
        if (ui_data_len < sizeof(arr_buff))
        {
            memcpy(arr_buff, p_data, ui_data_len);
            arr_buff[ui_data_len] = '\0';
        }
        else
        {
            memcpy(arr_buff, p_data, sizeof(arr_buff)-1);
            arr_buff[sizeof(arr_buff)-1] = '\0';
        }

        d_data = frhton64(atof(arr_buff));
        frstr_append(p_st_str, (const char *)&d_data, sizeof(double));
        frwarn("__frreport_conver_llong[%f %s]\n", d_data, arr_buff);
    }
    else
    {
        frstr_append(p_st_str, (const char *)&d_data, sizeof(double));
    }

    return;
}

/*******************************************************************************
*  FUNC     :  date格式组织
*  ARGS     :  p_st_str         (Frstr*)
*           :  p_data           (出力数据)
*           :  ui_data_len      (出力数据长度)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __frreport_conver_date(Frstr *p_st_str, const char *p_data, unsigned int ui_data_len)
{
    char arr_buff[50];
    char *p_pos;
    long l_data = 0;
    unsigned int ui_len = 0;

    if(p_st_str == NULL )
        return;

    if(p_data == NULL)
        ui_data_len = 0;

    p_pos = arr_buff;
    *(int *)(p_pos+ui_len) = frhton32(sizeof(long));
    ui_len += sizeof(long);
    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);

    if(ui_data_len > 0)
    {
        if (ui_data_len < sizeof(arr_buff))
        {
            memcpy(arr_buff, p_data, ui_data_len);
            arr_buff[ui_data_len] = '\0';
        }
        else
        {
            memcpy(arr_buff, p_data, sizeof(arr_buff)-1);
            arr_buff[sizeof(arr_buff)-1] = '\0';
        }

        l_data = frhton64(atol(arr_buff));
        frstr_append(p_st_str, (const char *)&l_data, sizeof(long));
        //frwarn("__frreport_conver_date[%ld %s]\n", atol(arr_buff), arr_buff);
    }
    else
    {
        frstr_append(p_st_str, (const char *)&l_data, sizeof(long));
    }
    return;
}
#endif

/*******************************************************************************
*  FUNC     :  l7链表数据出力
*  ARGS     :  p_hdr            (链表头)
*           :  p_st_str         (Frstr*)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __frreport_conver_l7data_list(Frlist_header *p_hdr, Frstr *p_st_str)
{
    Frlist_node *p_st_node=NULL;
    Frvar_field *p_varfield=NULL;
    Frbindata *p_st_bindata = NULL;
    unsigned int ui_len=0;

    if(p_hdr == NULL || frlist_size(p_hdr) <= 0 || p_st_str == NULL)
        return;

    p_st_node = FRLIST_FIRST_NODE(p_hdr);
    while(p_st_node)
    {
        p_varfield =  (Frvar_field*)FRLIST_GET_NODE_DATA(p_st_node);
        if(p_varfield)
        {

            switch(p_varfield->em_data_type)
            {
                case FRLONG:
                    __frreport_conver_str(p_st_str, p_varfield->p_field_name, strlen(p_varfield->p_field_name));
                    __frreport_conver_llong(p_st_str, p_varfield->field_value.ll_value);
                    break;
                case FRFLOAT:
                    __frreport_conver_str(p_st_str, p_varfield->p_field_name, strlen(p_varfield->p_field_name));
                    __frreport_conver_double(p_st_str, p_varfield->field_value.f_value);
                    break;
                case FRDOUBLE:
                    __frreport_conver_str(p_st_str, p_varfield->p_field_name, strlen(p_varfield->p_field_name));
                    __frreport_conver_double(p_st_str, p_varfield->field_value.d_value);
                    break;
                case FRSTRING:
                    if(p_varfield->field_value.p_value)
                    {
                        #ifdef FRFRAME_CONVER_DOUBLE_DATE
                        ui_len = 0;
                        if(p_varfield->p_field_name )
                            ui_len = strlen(p_varfield->p_field_name);

                        if(ui_len > 2 && strcmp(p_varfield->p_field_name + ui_len -2 , ".d") == 0)
                        {
                            __frreport_conver_str(p_st_str, p_varfield->p_field_name, strlen(p_varfield->p_field_name));
                            __frreport_conver_date(p_st_str, p_varfield->field_value.p_value, strlen(p_varfield->field_value.p_value));
                        }
                        else if(ui_len > 2 && strcmp(p_varfield->p_field_name + ui_len -2 , ".l") == 0)
                        {
                            __frreport_conver_str(p_st_str, p_varfield->p_field_name, strlen(p_varfield->p_field_name));
                            __frreport_conver_double(p_st_str, p_varfield->field_value.p_value, strlen(p_varfield->field_value.p_value));
                        }
                        else
                        {
                            __frreport_conver_str(p_st_str, p_varfield->p_field_name, strlen(p_varfield->p_field_name));
                            __frreport_conver_str(p_st_str, p_varfield->field_value.p_value, strlen(p_varfield->field_value.p_value));
                        }
                        #else
                        __frreport_conver_str(p_st_str, p_varfield->p_field_name, strlen(p_varfield->p_field_name));
                        __frreport_conver_str(p_st_str, p_varfield->field_value.p_value, strlen(p_varfield->field_value.p_value));
                        #endif
                    }
                    break;
                case FRBLOB:
                case FRCLOB:
                    p_st_bindata = p_varfield->field_value.p_st_value;
                    if(p_st_bindata)
                    {
                        __frreport_conver_str(p_st_str, p_varfield->p_field_name, strlen(p_varfield->p_field_name));
                        __frreport_conver_str(p_st_str, p_st_bindata->p_data, p_st_bindata->ui_len);
                    }
                    break;
                default:
                    break;
            }
        }
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return;
}

/*******************************************************************************
*  FUNC     :  Frreport_l7data出力
*  ARGS     :  p_st_l7data      (Frreport_l7data*)
*           :  p_st_str         (Frstr*)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frreport_conver_l7data(Frreport_l7data  *p_st_l7data, Frstr *p_st_str)
{
    char arr_buff[FRREPORT_L7DATA_SIZE+1];
    char *p_pos;
    unsigned int ui_len = 0;

    if(p_st_l7data == NULL || p_st_str == NULL)
        return FR_FAIL;

    p_pos = arr_buff;
    *(int *)(p_pos+ui_len) = frhton32(p_st_l7data->ip_proto);
    ui_len += sizeof(int);
    *(long *)(p_pos+ui_len) = frhton64(p_st_l7data->src_ip);
    ui_len += sizeof(long);
    *(int *)(p_pos+ui_len) = frhton32(p_st_l7data->src_port);
    ui_len += sizeof(int);
    *(long *)(p_pos+ui_len) = frhton64(p_st_l7data->dst_ip);
    ui_len += sizeof(long);
    *(int *)(p_pos+ui_len) = frhton32(p_st_l7data->dst_port);
    ui_len += sizeof(int);
    *(int *)(p_pos+ui_len) = frhton32(p_st_l7data->i_l7_proto);
    ui_len += sizeof(int);

    *(p_pos+ui_len) = '\0';
    frstr_append(p_st_str, arr_buff, ui_len);

    __frreport_conver_l7data_list(&p_st_l7data->st_hdr_comm, p_st_str);
    __frreport_conver_l7data_list(&p_st_l7data->st_hdr_req, p_st_str);
    __frreport_conver_l7data_list(&p_st_l7data->st_hdr_resp, p_st_str);
    __frreport_conver_l7data_list(&p_st_l7data->st_hdr_mq, p_st_str);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  Frreport_body_data出力
*  ARGS     :  p_st_body_data   (Frreport_body_data*)
*           :  p_st_str         (Frstr*)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frreport_conver_body(Frreport_body_data  *p_st_body_data, Frstr *p_st_str)
{
    int i_ret = FR_FAIL;
    if(p_st_body_data == NULL || p_st_str == NULL)
        return FR_FAIL;

    switch(p_st_body_data->em_type)
    {
        case FRREPORT_TYPE_STAT_PORT:
            i_ret = __frreport_conver_stat_port( &p_st_body_data->un_data.st_stat_port, p_st_str);
            break;
        case FRREPORT_TYPE_STAT_CONN:
            i_ret = __frreport_conver_stat_conn( &p_st_body_data->un_data.st_stat_conn, p_st_str);
            break;
        case FRREPORT_TYPE_L7DATA:
            i_ret = __frreport_conver_l7data( &p_st_body_data->un_data.st_l7data, p_st_str);
            break;
        case FRREPORT_TYPE_STAT_L4:
            i_ret = __frreport_conver_stat_l4_tcp( &p_st_body_data->un_data.st_stat_l4_tcp, p_st_str);
            break;
        default:
            break;
    }

    return i_ret;
}
/*******************************************************************************
*  FUNC     :  转换report数据
*  ARGS     :  p_st_report_data     转换前的数据
*           :  pp_data_out          转换后的内容
*           :  p_ui_data_len        转换后的内容的长度
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :  pp_data_out需要外面释放内存
*******************************************************************************/
int frreport_convert(Frreport_data *p_st_report_data
                   , char **pp_data_out
                   , unsigned int *p_ui_data_len)
{
    Frlist_header *p_hdr_body=NULL;
    Frlist_node *p_st_node=NULL;
    Frreport_body_data *p_st_body_data=NULL;
    Frstr *p_st_str=NULL;
    char arr_header[FRREPORT_HEADER_SIZE];

    if (p_st_report_data == NULL || pp_data_out == NULL || p_ui_data_len==NULL)
        return FR_FAIL;

    p_st_str = frstr_new(1024);
    if(p_st_str == NULL)
    {
        FRLOG_ERROR_DETAIL("frstr_new err");
        return FR_FAIL;
    }

    memset(arr_header, 0x00, sizeof(arr_header));
    //预留头空间
    frstr_append(p_st_str, arr_header, sizeof(arr_header));

    p_hdr_body = &p_st_report_data->st_hdr_body;
    p_st_node = FRLIST_FIRST_NODE(p_hdr_body);
    while(p_st_node)
    {
        p_st_body_data =  (Frreport_body_data*)FRLIST_GET_NODE_DATA(p_st_node);
        if(p_st_body_data)
            __frreport_conver_body(p_st_body_data, p_st_str);
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    *p_ui_data_len = FRSTR_LEN(p_st_str);
    if(*p_ui_data_len < FRREPORT_HEADER_SIZE)
    {
        frstr_free(&p_st_str);
        return FR_FAIL;
    }

    *pp_data_out = frstr_free2(&p_st_str);
    frreport_set_body_len(p_st_report_data, *p_ui_data_len - FRREPORT_HEADER_SIZE);
    __frreport_conver_header(p_st_report_data->em_type, p_st_report_data->em_type_l7data, &p_st_report_data->st_data_header
                            , arr_header, sizeof(arr_header) );
    memcpy(*pp_data_out, arr_header, FRREPORT_HEADER_SIZE);
    return FR_SUCC;
}
